/*
 * Process.cpp
 *
 *  Created on: Jul 11, 2009
 *      Author: elkobir
 */

#include "Process.h"

// new process from the root
Process::Process(int id) {
	string _currPath = ""; // root
	int _pid = id;
	for (int i = 0; i < 12; i++){
		int emptyVal = -9; //  EMPTY_INDEX is -9 compiler broblems ?!?;
		_fdTable.push_back(emptyVal);
	}
	_commList = new UnboundedBlockingQueue();
}

// new process created not from the root
Process::Process(int id, string currPath){
	string _currPath = currPath;
	int _pid = id;
	for (int i = 0; i < 12; i++){
		int emptyVal = -9; //  EMPTY_INDEX is -9 compiler broblems ?!?;
		_fdTable.push_back(emptyVal);
	}
	_commList = new UnboundedBlockingQueue();
}

// new process with fork (same fd);
Process::Process(int id, Process father){
	_currPath = father._currPath;
	int _pid = id;
	for (int i = 0; i < 12; i++){
		_fdTable.push_back(father._fdTable.at(i));
	}
	_commList = new UnboundedBlockingQueue();
}

Process::~Process() {
	// TODO Auto-generated destructor stub
}

int Process::addFileDescriptor(int fd){
	int index = findIndexOfFileDescriptor(fd);
	if (index != -1){
		ostringstream str;
		str << "SysCall::addFileDescriptor - cannot add fd="<< fd;
		str << " to table because it's already there at index= " <<  index << endl;
		Log::log(str,0,"error");
		return -1;
	}

	int emptyIndex = findIndexOfFirstEmptySpace();
	if (emptyIndex == -1){
		ostringstream str;
		str << "SysCall::addFileDescriptor - cannot add fd="<< fd;
		str << " to table because the table is full." << endl;
		Log::log(str,0,"error");
		return -1;
	}

	_fdTable[emptyIndex] = fd;

	return 0;

}

int Process::removeFileDescriptor(int fd){
	int index = findIndexOfFileDescriptor(fd);
	if (index == -1){
		ostringstream str;
		str << "SysCall::removeFileDescriptor - cannot remove fd="<< fd;
		str << " to table because it's not there" << endl;
		Log::log(str,0,"error");
		return -1;
	}

	_fdTable[index] = EMPTY_INDEX;
	return 0;
}

int Process::findIndexOfFileDescriptor(int fd){
	for (unsigned int i = 0; i < _fdTable.size(); i++){
		if (_fdTable.at(i) == fd){
			return i;
		}
	}
	return -1;
}

int Process::findIndexOfFirstEmptySpace(){
	int emptyIndexValue = EMPTY_INDEX;
	for (unsigned int i = 0; i < _fdTable.size(); i++){
		if (_fdTable.at(i) == emptyIndexValue){
			return i;
		}
	}
	return -1;
}

void Process::sendMessage(string msg){
	_commList->addElement(msg);
}

void Process::processCommand(){

	string command = _commList->removeElement();

	vector<string> tokens;
	Utils::tokenize(command,tokens," ");

	if (tokens.at(0).compare("mkdir") == 0){
		//TODO
	}
	if (tokens.at(0).compare("create") == 0){
		//TODO
	}
	if (tokens.at(0).compare("hdlink") == 0){
		//TODO
	}
	if (tokens.at(0).compare("sflink") == 0){
		//TODO
	}
	if (tokens.at(0).compare("open") == 0){
		//TODO
	}
	if (tokens.at(0).compare("close") == 0){
		//TODO
	}
	if (tokens.at(0).compare("read") == 0){
		//TODO
	}
	if (tokens.at(0).compare("write") == 0){
		//TODO
	}
	if (tokens.at(0).compare("writeFile") == 0){
		//TODO
	}
	if (tokens.at(0).compare("lck_rd") == 0){
		//TODO
	}
	if (tokens.at(0).compare("lck_wr") == 0){
		//TODO
	}
	if (tokens.at(0).compare("rlslck_rd") == 0){
		//TODO
	}
	if (tokens.at(0).compare("rlslck_wr") == 0){
		//TODO
	}
	if (tokens.at(0).compare("lseek") == 0){
		//TODO
	}
	if (tokens.at(0).compare("rm") == 0){
		//TODO
	}
	if (tokens.at(0).compare("rmdir") == 0){
		//TODO
	}
	if (tokens.at(0).compare("rmdir_r") == 0){
		//TODO
	}
	if (tokens.at(0).compare("ls") == 0){
		//TODO
	}
	if (tokens.at(0).compare("mv") == 0){
		//TODO
	}
	if (tokens.at(0).compare("cd") == 0){
		//TODO
	}

}


string Process::getFullPathName(string path){

	bool isfullPath = path.at(0) == '/';
	vector<string>* currPath = Utils::tokPath(_currPath);
	if(isfullPath){
		currPath->clear();
	}
	vector<string>* relPath = Utils::tokPath(path);


	for(unsigned int i = 0; i < relPath->size(); i++){
		if(relPath->at(i).compare("..") == 0){
			if(currPath->size() < 1)
				Log::log("Error: cannot go behind root directory",0,"error");
			currPath->pop_back();
			continue;
		}
		if(relPath->at(i).compare(".") == 0){
			continue;
		}
		currPath->push_back(relPath->at(i));
	}

	ostringstream fp;
	for(unsigned int i = 0; i < currPath->size(); i++){
		fp << "/" << currPath->at(i);
	}

	return fp.str();
}

void Process::setpath(string path){
	_currPath = path;

}

